import xbmc, xbmcaddon, json
from follwitAddon import FollwitAddon
from xbmcInterface import FollwitXBMCInterface
from follwitAPI import FollwitAPI

class EventHandler():
    def __init__(self):
        self.abortRequested = False
        self.removePending = False
        self.removeData = None
        self.onStopFired = False
        self.onStopId = None
        self.currentEvent = None
        self.currentEventData = None
        self.previousEvent = None
        self.previousEventData = None
        self.bulkRemove = False
        self.bulkRemoveData = list()
        self.bulkAdd = False
        self.bulkAddData = list()
        self.follwitAddon = FollwitAddon()
        self.follwitAddon.getXBMCEpisodes()
        self.follwitAddon.getXBMCMovies()
        if self.follwitAddon.debug:
            self.debug = True
        else:
            self.debug = False
    
    # method to handle what to do with the event.
    # @param data       event json data
    def event(self, data):
        self.checkEventData(data)
        if data['method'] == 'Player.OnStop':
            self.onStop(data)
        elif data['method'] == 'VideoLibrary.OnRemove':
            self.onRemove(data)
        elif data['method'] == 'Player.OnPlay':
            self.onPlay(data)
        elif data['method'] == 'VideoLibrary.OnUpdate':
            self.onUpdate(data)
        elif data['method'] == 'System.OnQuit':
            self.onQuit(data)
        else:
            if self.debug:
                print '[Follwit Event] message: unused method fired '+data['method']
    
    # method to handle xbmc quit event.
    # @param data       event json data 
    def onQuit(self, data):
        if self.debug:
            print '[Notification Service] message: System quit requested'
        self.follwitAddon.follwitAPI.close()
        
    # @param data       event json data
    def onRemove(self, data):
        if self.debug:
            print '[Notification Service] message: library remove'
        if 'id' in data['params']['data'] and 'type' in data['params']['data']:
            type = data['params']['data']['type']
            id = data['params']['data']['id']
            if self.bulkRemove:
                oldRemoveData = self.removeData
            if type == 'movie':
                if self.debug:
                    print '[Notification Service] removal request for movie'
                for movie in self.follwitAddon.xbmcMovies:
                    if movie['movieid'] == id:
                        data['params']['data']['imdbnumber'] = movie['imdbnumber']
                        self.removeData = data
                        self.removePending = True
                        if self.debug:
                            print '[Follwit Event] message: removal pending for ' + self.removeData['params']['data']['imdbnumber']
                        break
            elif type == 'episode':
                if self.debug:
                    print '[Notification Service] add removal request for episode'
                for episode in self.follwitAddon.xbmcEpisodes:
                    if episode['episodeid'] == id:
                        data['params']['data']['episode'] = episode['episode']
                        data['params']['data']['season'] = episode['season']
                        data['params']['data']['tvshowid'] = episode['tvshowid']
                        data['params']['data']['showtitle'] = episode['showtitle']
                        self.removeData = data
                        self.removePending = True
                        if self.debug:
                            print '[Follwit Event] message: removal pending for : ' + self.removeData['params']['data']['showtitle'] + ' S'+str(self.removeData['params']['data']['season'])+'E'+str(self.removeData['params']['data']['episode'])
                        break
            if self.bulkRemove:
                if type == oldRemoveData['params']['data']['type']:
                    if type == 'movie':
                        if self.debug:
                            print '[Notification Service] bulk removal request for movie'
                        if len(self.bulkRemoveData) < 75:
                            self.bulkRemoveData.append(oldRemoveData)
                        else:
                            self.processBulkRemove()
                            self.bulkRemoveData.append(oldRemoveData)
                    elif type == 'episode':
                        if self.debug:
                            print '[Notification Service] bulk removal request for episode'
                        if len(self.bulkRemoveData) < 75:
                            self.bulkRemoveData.append(oldRemoveData)
                        else:
                            self.processBulkRemove()
                            self.bulkRemoveData.append(oldRemoveData)
                else:
                    self.processRemove(oldRemoveData, False)
                    if len(self.bulkRemoveData) > 0:
                        self.processBulkRemove()
    # @param data       event json data
    def onUpdate(self, data):
        if self.debug:
            print '[Notification Service] message: library update'
        if self.removePending:
            if self.eventHasItem:
                if self.eventType == self.removeData['params']['data']['type']:
                    if self.eventType == 'movie':
                        imdbid = self.follwitAddon.xbmcInt.getMovieIMDB(self.eventId)
                        if imdbid == self.removeData['params']['data']['imdbnumber']:
                            if self.debug:
                                print '[Follwit Event] Clear removal pending for ' + self.removeData['params']['data']['imdbnumber']
                            self.removeData = None
                            self.removePending = False
                            return
                        else:
                            #imdb of update is different from the pending remove request. process remove request
                            self.processRemove(self.removeData)
                    elif data['params']['data']['item']['type'] == 'episode':
                        #get episode info for current update
                        epInfo = self.follwitAddon.xbmcInt.getEpisodeTVDB(self.eventId)
                        #check if current update is for the same episode as the remove request if so clear remove request
                        if epInfo['showtitle'] == self.removeData['params']['data']['showtitle'] and epInfo['season'] == self.removeData['params']['data']['season'] and epInfo['episode'] == self.removeData['params']['data']['episode']:
                            if self.debug:
                                print '[Notification Service] message: clear removal pending for : ' + self.removeData['params']['data']['showtitle'] + ' S'+str(self.removeData['params']['data']['season'])+'E'+str(self.removeData['params']['data']['episode'])
                            self.removeData = None
                            self.removePending = False
                            return
                        else:
                            self.processRemove(self.removeData)
                else:
                    self.processRemove(self.removeData)
            else:
                self.processRemove(self.removeData)
        if self.onStopFired:
            self.onStopFired = False
            if self.onStopId == self.eventId:
                if self.debug:
                    print '[Notification Service] message: updating stopped item'
                    
                self.onStopId = False
                return
        if self.hasPlaycount:
            if self.eventType == 'movie':
                imdbid = self.follwitAddon.xbmcInt.getMovieIMDB(self.eventId)
                if not imdbid == False:
                    if self.playcount > 0:
                        if self.debug:
                            print '[Follwit Event] Sending movie watched request to Follw.it API.'
                        self.follwitAddon.follwitAPI.watchedMovie('imdb_id', imdbid)
                    else:
                        if self.debug:
                            print '[Follwit Event] Sending movie not watched request to Follw.it API.'
                        self.follwitAddon.follwitAPI.notWatchedMovie('imdb_id', imdbid)
            elif self.eventType == 'episode':
                epInfo = self.follwitAddon.xbmcInt.getEpisodeTVDB(self.eventId)
                if not epInfo == False:
                    if self.playcount > 0:
                        if self.debug:
                            print '[Follwit Event] Sending episode watched request to Follw.it API.'
                        self.follwitAddon.follwitAPI.watchedEpisode(epInfo['tvshowid'], epInfo['season'], epInfo['episode'])
                    else:
                        if self.debug:
                            print '[Follwit Event] Sending episode not watched request to Follw.it API.'
                        self.follwitAddon.follwitAPI.notWatchedEpisode(epInfo['tvshowid'], epInfo['season'], epInfo['episode'])
        else:
            if self.bulkAdd:
                if self.eventType == self.previousEventData['params']['data']['item']['type']:
                    if self.eventType == 'movie':
                        if self.debug:
                            print '[Follwit Event] bulk add request for movie'
                        if len(self.bulkAddData) < 75:
                            self.bulkAddData.append(data)
                        else:
                            self.processBulkAdd()
                            self.bulkAddData.append(data)
                        return
                    if self.eventType == 'episode':
                        if self.debug:
                            print '[Follwit Event] bulk add request for episode'
                        if len(self.bulkAddData) < 75:
                            self.bulkAddData.append(data)
                        else:
                            self.processBulkAdd()
                            self.bulkAddData.append(data)
                        return
                else:
                    if len(self.bulkAddData) > 0:
                        self.processBulkAdd()
                
            #this is some information in the video library changing other than a playcount change
            if self.eventType == 'movie':
                imdbid = self.follwitAddon.xbmcInt.getMovieIMDB(self.eventId)
                if self.debug:
                    print '[Follwit Addon] New movie added to video library'
                #add movie to follwit and update internal movie list
                if not imdbid == False:
                    self.follwitAddon.follwitAPI.addMovie('imdb_id', imdbid)
                    self.follwitAddon.getXBMCMovies()
            elif self.eventType == 'episode':
                epInfo = self.follwitAddon.xbmcInt.getEpisodeTVDB(self.eventId)
                if self.debug:
                    print '[Follwit Addon] New episode added to video library'
                if not epInfo == False:
                    self.follwitAddon.follwitAPI.addEpisode(epInfo['tvshowid'], epInfo['season'], epInfo['episode'])
                    self.follwitAddon.getXBMCEpisodes()
    
    # @param data       event json data
    def onPlay(self, data):
        if self.debug:
            print '[Notification Service] message: player started'
        if self.eventHasItem:
            if self.eventType == 'movie':
                imdbid = self.follwitAddon.xbmcInt.getMovieIMDB(self.eventId)
                if not imdbid == False:
                    if self.debug:
                        print '[Follwit Event] Sending movie watching request to Follw.it API.'
                    self.follwitAddon.follwitAPI.watchingMovie('imdb_id', imdbid)
            elif self.eventType == 'episode':
                epInfo = self.follwitAddon.xbmcInt.getEpisodeTVDB(self.eventId)
                if not epInfo == False:
                    if self.debug:
                        print '[Follwit Addon] Sending episode watching request to Follw.it API.'
                    self.follwitAddon.follwitAPI.watchingEpisode(epInfo['tvshowid'], epInfo['season'], epInfo['episode'])
    
    # @param data       event json data
    def onStop(self, data):
        self.onStopFired = True
        if self.debug:
            print '[Notification Service] message: player stopped'
        if self.eventHasItem:
            self.onStopId = self.eventId
        else:
            self.eventId = False
        if self.eventHasItem:
            if self.eventType == 'movie':
                imdbid = self.follwitAddon.xbmcInt.getMovieIMDB(self.eventId)
                if not imdbid == False:
                    if self.debug:
                        print '[Follwit Event] Sending movie not watching request to Follw.it API.'
                    self.follwitAddon.follwitAPI.notWatchingMovie('imdb_id', imdbid)
            elif self.eventType == 'episode':
                epInfo = self.follwitAddon.xbmcInt.getEpisodeTVDB(self.eventId)
                if not epInfo == False:
                    if self.debug:
                        print '[Follwit Event] Sending episode not watching request to Follw.it API.'
                    self.follwitAddon.follwitAPI.notWatchingEpisode(epInfo['tvshowid'], epInfo['season'], epInfo['episode'])
        if self.nullData:
            if self.debug:
                # this happens when an item is watched to completion and no resume timestamp is needed
                print '[Follwit Addon] eventOnStop with null data received'
    
    # method that does various data checks to prevent the need
    # of doing them over and over again later on in other methods
    # @param data       event json data
    def checkEventData(self, data):
        self.eventHasItem = False
        self.nullData = False
        self.hasPlaycount = False
        self.eventId = False
        self.eventType = False
        self.bulkRemove = False
        self.bulkAdd = False
        self.previousEvent = self.currentEvent
        self.previousEventData = self.currentEventData
        self.currentEventData = data
        self.currentEvent = data['method']
        if 'data' in data['params']:
            if data['params']['data'] is None:
                self.nullData = True
            elif 'item' in data['params']['data']:
                if 'playcount' in data['params']['data']:
                    self.hasPlaycount = True
                    self.playcount = data['params']['data']['playcount']
                if 'id' in data['params']['data']['item'] and 'type' in data['params']['data']['item']:
                    self.eventHasItem = True
                    self.eventId = data['params']['data']['item']['id']
                    self.eventType = data['params']['data']['item']['type']
        if self.removePending and self.currentEvent == 'VideoLibrary.OnRemove':
            self.bulkRemove = True
        if self.previousEvent == 'VideoLibrary.OnUpdate' and self.currentEvent == 'VideoLibrary.OnUpdate':
            self.bulkAdd = True
        if self.removePending and not self.bulkRemove and self.currentEvent != 'VideoLibrary.OnUpdate':
            self.processRemove(self.removeData)
        if self.onStopFired and self.currentEvent != 'VideoLibrary.OnUpdate':
            self.onStopFired = False
        if len(self.bulkRemoveData) > 0 and self.currentEvent != 'VideoLibrary.OnRemove':
            self.processBulkRemove()
        if len(self.bulkAddData) > 0 and self.currentEvent != 'VideoLibrary.OnUpdate':
            self.processBulkAdd()
    
    #method to process a remove request
    def processRemove(self, data, clearData=True):
        #call remove event and clear local remove data
        data = data['params']['data']
        if data['type'] == 'movie':
            self.follwitAddon.follwitAPI.removeMovie('imdb_id', data['imdbnumber'])
        elif data['type'] == 'episode':
            self.follwitAddon.follwitAPI.removeEpisode(self.follwitAddon.xbmcTvShows[data['tvshowid']], data['season'], data['episode'])
        if clearData:
            self.removeData = None
            self.removePending = False
    
    def processBulkRemove(self):
        if self.debug:
            print '[Follwit Event] processing bulk remove'
        data = self.bulkRemoveData
        self.bulkRemoveData = list()
        if self.debug:
            print '[Follwit Event] bulk length '+str(len(data))
        if len(data) > 0:
            type = data[0]['params']['data']['type']
            if self.debug:
                print '[Follwit Event] bulk type '+str(data[0]['params']['data']['type'])
            tempBulk = {}
            if type == 'episode':
                tempBulk['episodes'] = []
                for xbmcEpisode in data:
                    if not False:
                        temp = {}
                        temp['in_collection'] = False
                        temp['tvdb_series_id'] = self.follwitAddon.xbmcTvShows[xbmcEpisode['params']['data']['tvshowid']]
                        temp['season_number'] = xbmcEpisode['params']['data']['season']
                        temp['episode_number'] = xbmcEpisode['params']['data']['episode']
                        tempBulk['episodes'].append(temp)
                self.follwitAddon.follwitAPI.remoteAPI('POST', 'episode.bulk_action', tempBulk, True)
            elif type == 'movie':
                tempBulk['movies'] = []
                for xbmcMovie in data:
                    if not xbmcMovie['params']['data']['imdbnumber'] == '':
                        temp = {}
                        temp['resources'] = 'imdb.com='+xbmcMovie['params']['data']['imdbnumber']
                        temp['in_collection'] = False
                        tempBulk['movies'].append(temp)
                self.follwitAddon.follwitAPI.remoteAPI('POST', 'movie.bulk_action', tempBulk, True)
                
    def processBulkAdd(self):
        if self.debug:
            print '[Follwit Event] processing bulk add'
        data = self.bulkAddData
        self.bulkAddData = list()
        if self.debug:
            print '[Follwit Event] bulk length '+str(len(data))
        if len(data) > 0:
            type = data[0]['params']['data']['item']['type']
            if self.debug:
                print '[Follwit Event] bulk type '+str(type)
            tempBulk = {}
            if type == 'episode':
                tempBulk['episodes'] = []
                for xbmcEpisode in data:
                    epInfo = self.follwitAddon.xbmcInt.getEpisodeTVDB(xbmcEpisode['params']['data']['item']['id'])
                    if not epInfo == False:
                        temp = {}
                        temp['in_collection'] = True
                        temp['tvdb_series_id'] = epInfo['tvshowid']
                        temp['season_number'] = epInfo['season']
                        temp['episode_number'] = epInfo['episode']
                        tempBulk['episodes'].append(temp)
                self.follwitAddon.follwitAPI.remoteAPI('POST', 'episode.bulk_action', tempBulk, True)
            elif type == 'movie':
                tempBulk['movies'] = []
                for xbmcMovie in data:
                    imdbid = self.follwitAddon.xbmcInt.getMovieIMDB(xbmcMovie['params']['data']['item']['id'])
                    if not imdbid == False:
                        temp = {}
                        temp['resources'] = 'imdb.com='+imdbid
                        temp['in_collection'] = True
                        tempBulk['movies'].append(temp)
                self.follwitAddon.follwitAPI.remoteAPI('POST', 'movie.bulk_action', tempBulk, True)